#ifndef __FIBER_TIMER_H__
#define __FIBER_TIMER_H__

#include <memory>       // 智能指针（std::shared_ptr、std::weak_ptr等）
#include <set>          // 有序集合（用于存储定时器，按执行时间排序）
#include <vector>       // 动态数组（用于存储过期的回调函数）
#include <functional>   // 函数包装器
#include <cstdint>      // 无符号整型
#include "mutex.h"      // 互斥锁（RWMutex，保证多线程安全）

namespace fiber 
{

// 前置声明：TimerManager类，用于Timer类中声明友元
class TimerManager;

/**
 * @brief 定时器类：封装单个定时任务的属性和操作
 * 继承std::enable_shared_from_this<Timer>：允许对象生成自身的shared_ptr，方便在回调中安全引用
 */
class Timer : public std::enable_shared_from_this<Timer> {
    // 友元声明：TimerManager可访问Timer的私有成员（如构造函数）
    friend class TimerManager;

public:
    // 智能指针类型定义（方便管理定时器生命周期）
    using ptr = std::shared_ptr<Timer>;

    /**
     * @brief 取消当前定时器
     * @return 成功取消返回true，否则返回false（如已取消）
     */
    bool cancel();

    /**
     * @brief 刷新定时器：重新计算下次执行时间（基于当前时间和周期）
     * @return 成功刷新返回true
     */
    bool refresh();

    /**
     * @brief 重置定时器的周期和下次执行时间
     * @param ms 新的周期（毫秒）
     * @param from_now 是否从当前时间开始计算下次执行时间（true：从现在开始；false：从原计划时间偏移）
     * @return 成功重置返回true
     */
    bool reset(uint64_t ms, bool from_now);

private:
    /**
     * @brief 构造函数（私有，仅TimerManager可创建）
     * @param ms 执行周期（毫秒）
     * @param cb 定时任务的回调函数
     * @param recuring 是否为循环定时器（true：执行后重新计算下次时间；false：仅执行一次）
     * @param manager 所属的定时器管理器
     */
    Timer(uint64_t ms, std::function<void()> cb, bool recuring, TimerManager *manager);

    /**
     * @brief 构造函数（私有，用于临时创建比较用的定时器）
     * @param next 下次执行时间（绝对时间，毫秒）
     */
    Timer(uint64_t next);

    // 是否是循环定时器（true：执行后自动重新调度；false：一次性）
    bool m_recurring = false;
    // 执行周期（毫秒，仅循环定时器有效）
    uint64_t m_ms = 0;
    // 下次执行的精确时间（绝对时间，从系统启动到现在的毫秒数，参考GetElapsedMS()）
    uint64_t m_next = 0;
    // 定时任务的回调函数（定时器到期时执行）
    std::function<void()> m_cb;
    // 所属的定时器管理器（用于关联到管理器的集合中）
    TimerManager* m_manager = nullptr;

    /**
     * @brief 比较器结构体：用于std::set对Timer::ptr的排序
     * 按定时器的下次执行时间（next_）从小到大排序，确保集合中最前面的是最近要执行的定时器
     * 这里是要通过智能指针进行比较，不是类型本身，因此不能直接重载operator<
     */
    struct Comparator {
        /**
         * @brief 重载比较运算符
         * @param lhs 左操作数（定时器指针）
         * @param rhs 右操作数（定时器指针）
         * @return true：lhs的下次执行时间早于rhs，应排在前面
         */
        bool operator()(const Timer::ptr &lhs, const Timer::ptr &rhs) const;
    };
};

/**
 * @brief 定时器管理器类：管理多个定时器的生命周期，负责检测过期任务并执行回调
 * 作为基类，提供定时器管理的核心逻辑，子类需实现具体的事件触发（如唤醒等待线程）
 */
class TimerManager {
    // 友元声明：Timer可访问TimerManager的私有成员
    friend class Timer;

public:
    /**
     * @brief 构造函数：初始化管理器
     */
    TimerManager();

    /**
     * @brief 析构函数（虚函数，允许子类重写）
     */
    virtual ~TimerManager();

    /**
     * @brief 添加一个定时器
     * @param ms 执行周期（毫秒）
     * @param cb 定时任务的回调函数
     * @param recuring 是否为循环定时器（默认false：一次性）
     * @return 新创建的定时器智能指针
     */
    Timer::ptr addTimer(uint64_t ms, std::function<void()> cb, bool recuring = false);

    /**
     * @brief 添加一个带条件的定时器（关联一个弱指针，条件失效时回调不执行）
     * @param ms 执行周期（毫秒）
     * @param cb 定时任务的回调函数
     * @param weak_cond 弱指针（指向条件对象，若对象已释放，回调不执行）
     * @param recuring 是否为循环定时器（默认false：一次性）
     * @return 新创建的定时器智能指针
     * 用途：避免回调访问已销毁的对象（如监听某个对象的事件，对象销毁后定时器自动失效）
     */
    Timer::ptr addConditionTimer(uint64_t ms, std::function<void()> cb, std::weak_ptr<void> weak_cond,
                                bool recurring = false);

    /**
     * @brief 获取到最近一个定时器执行的时间间隔（毫秒）
     * @return 时间间隔（若没有定时器，返回UINT64_MAX）
     */
    uint64_t getNextTimer();

    /**
     * @brief 获取所有已过期的定时器的回调函数
     * @param cbs 用于存储过期回调的向量（输出参数）
     */
    void listExpiredCb(std::vector<std::function<void()>> &cbs);

    /**
     * @brief 判断管理器中是否有定时器
     * @return true：存在至少一个定时器；false：无定时器
     */
    bool hasTimer();

protected:
    /**
     * @brief 纯虚函数：当新的定时器插入到集合首部（即成为最近要执行的定时器）时调用
     * 子类需实现此函数（通常用于唤醒等待的线程，重新计算等待时间）
     */
    virtual void OnTimerInsertedAtFront() = 0;

    /**
     * @brief 将定时器添加到管理器的集合中（内部使用，需配合写锁）
     * @param val 要添加的定时器指针
     * @param lock 已获取的写锁（确保线程安全）
     */
    void addTimer(Timer::ptr val, RWMutex::WriteLock &lock);

private:
    /**
     * @brief 检测系统时钟是否回滚（如系统时间被人为调小）
     * @param now_ms 当前时间（毫秒）
     * @return true：时钟回滚；false：正常
     * 用途：避免因时钟回滚导致定时器错误触发（如把过去的时间当成未来时间）
     */
    bool detectClockRolllover(uint64_t now_ms);

    /// 读写锁：保护定时器集合的线程安全（读多写少场景优化）
    RWMutex m_rwmutex;
    /// 定时器集合：按下次执行的绝对时间排序（通过Timer::Comparator），存储所有活跃定时器
    std::set<Timer::ptr, Timer::Comparator> m_timers;
    /// 标记是否已触发OnTimerInsertedAtFront（避免重复触发）
    bool m_tickled = false;
    /// 上次处理定时器的时间（毫秒）：用于检测时钟回滚和计算下次执行时间
    uint64_t m_previouseTime = 0;
};

}  // namespace fiber

#endif  // __FIBER_TIMER_H__